package com.kfm.src.Demo1005;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class JDBCUtil<T>{
   private  String url;
   private String user;
   private String pass;
   private Connection conn;
   private PreparedStatement ps;
   private ResultSet rs;

   private Boolean autoCommit=true;

    static {
       try {
           Class.forName("com.mysql.cj.jdbc.Driver");
       } catch (ClassNotFoundException e) {
           throw new RuntimeException(e);
       }
   }

    /**
     * 加入事务管理
     */
    public void startTransaction(){

        try {
            getConnection();
            if (conn!=null&&conn.isClosed()&&autoCommit==true){
                conn.setAutoCommit(false);
                autoCommit=true;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     *事务提交
     */
    public void commit(){
        try {
            if (conn!=null&&conn.isClosed()&&autoCommit==false){
               conn.commit();
               autoCommit=true;

            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 事务回滚‘
     */
    public void rollock(){
        try {
            if (conn!=null&&conn.isClosed()&&autoCommit==false){
                conn.rollback();
                autoCommit=true;

            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 关闭资源操作
     */
   public void close(){
       if (conn!=null){
           try {
               conn.close();
           } catch (SQLException e) {
               throw new RuntimeException(e);
           }
       }
       if (ps!=null){
           try {
               ps.close();
           } catch (SQLException e) {
               throw new RuntimeException(e);
           }
       }
       if (rs!=null){
           try {
               rs.close();
           } catch (SQLException e) {
               throw new RuntimeException(e);
           }
       }
   }

    /**
     * 获取数据库链接对象
     */

    public JDBCUtil(String url, String user, String pass){
        this.url=url;
        this.pass=pass;
        this.user=user;
    }
   public Connection  getConnection(){
       try {
           if (conn==null||conn.isClosed()) {
               conn = DriverManager.getConnection(url, user, pass);
           }
       } catch (SQLException e) {
           throw new RuntimeException(e);
       }
       return conn;
   }

    private <T> T mapper(ResultSet set, Class<T> cla) {
        try {
            //获取对象
            Constructor<T> declaredConstructor = cla.getDeclaredConstructor();
            declaredConstructor.setAccessible(true);
            T t = declaredConstructor.newInstance();
            //解析结果集
            ResultSetMetaData metaData = set.getMetaData();
            int columnCount = metaData.getColumnCount();
            for (int i = 1; i <=columnCount ; i++) {
                // 获取列名 getColumnLabel 和 getColumnName 的区别：前者获取别名，后者获取列名
                String columnName = metaData.getColumnLabel(i).toLowerCase();
                //判断是否有多个单词组成
                if (columnName.contains("_")){
                    columnName=toCamelCase(columnName);
                }

                try {
                    // 获取属性描述器
                    PropertyDescriptor propertyDescriptor=new PropertyDescriptor(columnName,cla);
                    //读方法
                    Method writeMethod = propertyDescriptor.getWriteMethod();
                    //获取访问权限
                    writeMethod.setAccessible(true);
                    Object value = set.getObject(i);
                    writeMethod.invoke(t,value);
                } catch (Exception e) {
                    System.err.println("没有对应的属性"+columnCount);

                }


            }
            return t;
        } catch (Exception e) {

            throw new RuntimeException(e);
        }

    }

    private String toCamelCase(String lowerCase) {
        //判断是否有多个单词组成
        if (lowerCase.contains("_")){
            String[] split = lowerCase.split("_");
            StringBuilder sb=new StringBuilder(split[0]);
            for (int i = 1; i < split.length; i++) {
                String s = split[i];
                sb.append(s.substring(0,1).toUpperCase()).append(s.substring(1).toLowerCase());
            }
            return sb.toString();
        }
        return lowerCase;
    }

    /*
       新增、修改、删除操作
     */
   public int update(String sql,Object... params) throws SQLException {
       int update = Update(sql, PreparedStatement.NO_GENERATED_KEYS, params);
       if (update>0){
           return update;
       }
       return -1;


   }

    /**
     * 新增操作 返回自增主键的值
     */
   public int insert(String sql,Object... params) throws SQLException {
       int update = update(sql, PreparedStatement.RETURN_GENERATED_KEYS, params);
       if (update>0){
           return update;
       }
       return -1;
   }


    /**
     *统一跟新
     * @param sql
     * @param parms
     * @return
     */
   public int Update(String sql,int autoGeneratedKey,Object... parms) throws SQLException {
       //获取链接
       getConnection();
       //预编译sql
       ps=conn.prepareStatement(sql,autoGeneratedKey);
       //设置值
       setParms(parms);
       //执行跟新
       int count = ps.executeUpdate();
       return count;


   }

    /**
     * 统一设置值
     * @param parms
     * @throws SQLException
     */
    private void setParms(Object[] parms) throws SQLException {
       if (parms!=null) {
           for (int i = 0; i < parms.length; i++) {
               ps.setObject(i+1,parms[i]);
           }
       }
    }


    /**
     * 查询单个对象返回
     * @param sql

     * @param params
     * @return
     * @throws SQLException
     */
    public T getOne(String sql, Class<T> cla, Object... params) throws SQLException {
        ResultSet rs = select(sql, cla, params);
        while (rs.next()) {
            return mapper(rs,cla);
        }
        return null;
    }

    /*
     * 查询所有的并返回对象结果集
     * @param sql
     * @param mapper
     * @param params
     * @return
     * @throws SQLException
     /
     */

    public List<T> getAll(String sql, ResultSetMapper<T> mapper, Object... params) throws SQLException {
        ResultSet select = select(sql, mapper, params);
        List<T> list=new ArrayList<>();
        while (select.next()) {
            T t = mapper.resultMapper(select);
            list.add(t);
        }
        return list;

    }

    /**
     * 查询所有的并返回对象结果集
     * @param sql

     * @param params
     * @return
     * @throws SQLException
     */
    public List<T> getAll(String sql, Class<T> cla, Object... params) throws SQLException {
        ResultSet select = select(sql, cla, params);
        List<T> list=new ArrayList<>();
        while (select.next()) {
            T t = mapper(select,cla);
            list.add(t);
        }
        return list;

    }

    /*
     * 统一查询
     * @param sql
     * @param mapper
     * @param params
     * @return
     * @throws SQLException
     /
     */
    private ResultSet select(String sql,ResultSetMapper<T> mapper, Object... params) throws SQLException {
        getConnection();
        ps=conn.prepareStatement(sql);
        setParms(params);
        rs=ps.executeQuery();
        return rs;
    }
    /**
     * 统一查询,反射
     * @param sql

     * @param params
     * @return
     * @throws SQLException
     */
    private ResultSet select(String sql,Class<T> cla , Object... params) throws SQLException {
        getConnection();
        ps=conn.prepareStatement(sql);
        setParms(params);
        rs=ps.executeQuery();
        return rs;
    }

    /**
     * 查询结果映射到对象
     *
     *
     * @param <T>
     */
    @FunctionalInterface
    public interface ResultSetMapper<T>{
        T resultMapper(ResultSet resultSet);
    }


}
